package com.auditlog.sql.runner;

import cn.hutool.core.util.StrUtil;
import com.auditlog.datasource.ParametersHolder;
import com.auditlog.datasource.StatementProxy;
import com.auditlog.datasource.db.SqlType;
import com.auditlog.sql.wrapper.DeleteDeParserWrapper;
import com.auditlog.datasource.struct.RecordImage;
import com.auditlog.datasource.struct.StatementMetaData;
import com.auditlog.datasource.struct.TableRecord;
import com.auditlog.util.IndexUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.statement.delete.Delete;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Zhiyang.Zhang
 * @version 1.0
 * @date 2022/10/24 15:38
 */
@Slf4j
public class DeleteSqlRunner<T extends java.sql.Statement> extends AbstractSqlRunner<T, Delete> {

    public DeleteSqlRunner(StatementProxy<T> statementProxy, Delete delete) {
        super(statementProxy, delete);
    }

    @Override
    public RecordImage beforeImage() throws Exception {
        StatementMetaData metaData = this.getMetaData(this.getStatement());
        String sql = metaData.getTableRecordsSql();
        List<Integer> placeHolders = new ArrayList<>();
        if (this.getStatementProxy() instanceof ParametersHolder) {
            Map<Integer, ArrayList<Object>> parameters = ((ParametersHolder) this.getStatementProxy()).getParameters();
            placeHolders.addAll(parameters.keySet());
        }
        String alias = StrUtil.isNotBlank(this.getAlias()) ? this.getAlias() : this.getTableName();
        List<String> allColumns = this.getTableMeta().getColumnNamesByOrder(alias);
        List<String> primaryKeyWithAlias = this.getTableMeta().getPrimaryKeyWithAlias(alias, true);
        PlaceHolderSqlContext sqlContext = this.getCurrentSqlContext(sql, placeHolders, true);
        List<List<Object>> result = this.executeParametersHolderSqlWithLockTable(sqlContext);
        TableRecord tableRecord = this.buildTableRecord(result, primaryKeyWithAlias, allColumns);
        List<Integer> indexList = IndexUtils.getIndexList(primaryKeyWithAlias, allColumns);
        List<List<Object>> pkValues = this.getIndexValue4List(result, indexList, false);
        return RecordImage.builder().beforeRecord(tableRecord)
                .sqlType(SqlType.DELETE)
                .possibleUpdateOrDeletePks(pkValues)
                .tableName(this.getTableName())
                .tableMeta(this.getTableMeta())
                .pkColumnsName(primaryKeyWithAlias)
                .alias(alias)
                .build();
    }

    @Override
    public RecordImage afterImage(RecordImage beforeRecordImage) throws Exception {
        // 删除之后没有任何记录了
        this.handleDeleteAfterRecordImage(beforeRecordImage);
        return beforeRecordImage;
    }

    @Override
    public StatementMetaData getMetaData(Delete statement) {
        List<String> columnNamesByOrder =
                this.getTableMeta().getColumnNamesByOrder(StrUtil.isNotBlank(this.getAlias()) ? this.getAlias() : this.getTableName());
        DeleteDeParserWrapper deleteDeParserWrapper = new DeleteDeParserWrapper();
        String sql = deleteDeParserWrapper.deSelectParse(statement, columnNamesByOrder);
        // 所有的占位符都是
        return StatementMetaData.builder().sqlType(SqlType.DELETE)
                .placeHolderIndex(deleteDeParserWrapper.getValidPalceholderIndex())
                .tableName(this.getTableName())
                .sqlRunner(this)
                .tableRecordsSql(sql)
                .build();
    }
}
